﻿using System.Collections.Generic;
using ThinkDotNetEditorLib.States;

namespace ThinkDotNetEditorLib.Commands
{
    public class CommandManager
    {
        private CommandManager()
        {
        }
        #region Fields\Constants

        public List<ICommand> _states = new List<ICommand>();
        private int _currentStateIndex;
        private const int MaxStatesNumberInBuffer = 5;
        
        #endregion        

        #region Properties

        public bool CanRedo
        {
            get { return _currentStateIndex < _states.Count; }
        }

        public bool CanUndo
        {
            get { return _currentStateIndex - 1 >= 0; }
        }

        #endregion

        #region Public Methods

        public void Execute(ICommand command)
        {
            command.Execute();
            _states.Insert(_currentStateIndex, command);
            _states.RemoveRange(_currentStateIndex + 1, _states.Count - 1 - _currentStateIndex);
            _currentStateIndex++;

            if (_states.Count > MaxStatesNumberInBuffer)
            {
                _states.RemoveAt(0);
                _currentStateIndex = _states.Count;
            }
        }

        public void Clear()
        {
            _currentStateIndex = 0;
            _states.Clear();
        }

        public void Redo()
        {
            if (CanRedo == false)
                return;

            ICommand command = _states[_currentStateIndex];

            command.Execute();
            _currentStateIndex++;
        }

        public void Undo()
        {
            if (CanUndo == false)
                return;

            ICommand command = _states[_currentStateIndex - 1];

            command.Rollback();
            _currentStateIndex--;
        }

        #endregion

        #region Singleton

        private static CommandManager _instance;

        public static CommandManager Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new CommandManager();
                return _instance;
            }
        }

        #endregion
    }
}
